package com.fw.core;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.fw.aop.Interceptor;

public class ActionInvocation {

	private Controller controller;
	private Interceptor[] inters;
	private Action action;
	private int index = 0;

	private static final Object[] NULL_ARGS = new Object[0];

	protected ActionInvocation() {
	}

	ActionInvocation(Action action, Controller controller) {
		this.controller = controller;
		this.inters = action.getInterceptors();
		this.action = action;
	}

	public void invoke() {
		if (index < inters.length) {
			inters[index++].intercept(this);
		} else if (index++ == inters.length) {
			try {
				Method method = action.getMethod();
				Class<?>[] paraTypes = method.getParameterTypes();
				if(paraTypes != null) {
					if(paraTypes.length == 0) {
						action.getMethod().invoke(controller, NULL_ARGS);
					} else {
						Object[] args = new Object[paraTypes.length];
						for (int i = 0; i < paraTypes.length; i++) {
							args[i] = controller.getModel(paraTypes[i]);
						}
						action.getMethod().invoke(controller, args);
					}
				}
			} catch (InvocationTargetException e) {
				Throwable cause = e.getTargetException();
				if (cause instanceof RuntimeException) {
					throw (RuntimeException) cause;
				}
				throw new RuntimeException(e);
			} catch (RuntimeException e) {
				throw e;
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}
	
	public Controller getController() {
		return controller;
	}

	public String getActionKey() {
		return action.getActionKey();
	}

	public String getControllerKey() {
		return action.getControllerKey();
	}

	public Method getMethod() {
		return action.getMethod();
	}

	public String getMethodName() {
		return action.getMethodName();
	}

	public String getViewPath() {
		return action.getViewPath();
	}
}
